#ifndef STREAMRECORDER_H
#define STREAMRECORDER_H
#include "segmentsmerger.h"
#include "streamrecorderconfig.h"
#include <atomic>
#include <memory>
#include <QDateTime>
#include <QMutex>
#include <QProcess>
#include <QTimer>

/**
 * @class StreamRecorder
 *
 * @brief
 * 此类提供了一个高级流媒体转换器，用于将输入流转换为指定格式的输出文件，并支持动态调整编码参数和处理信号。此类完全由DeepSeek生成。
 *
 * 使用说明：
 * -
 * 基础使用：创建一个配置对象`StreamRecorder::Config`，设置输入源、输出路径、编码参数、缓冲区大小等参数。然后，通过此配置
 * 创建`StreamRecorder`实例并调用`start()`方法开始转换过程。
 *   示例代码如下：
 *   ```
 *   StreamRecorder::Config config{
 *       "rtmp://input",    // 输入源地址
 *       "output.mp4",      // 输出文件路径
 *       {"-c:v", "libx264", "-preset", "fast"},  // 编码参数
 *       5,                 // 输入缓冲区大小（秒）
 *       5000,              // 最大比特率（kbps）
 *       true,              // 是否启用硬件加速
 *       3000               // 目标视频比特率（kbps）
 *   };
 *   StreamRecorder converter(config);
 *   converter.start();
 *   ```
 *
 * -
 * 动态调整参数：可以使用`adjustEncodingParams`方法在运行时调整编码参数，如改变比特率或质量因子(CRF)等。
 *   示例代码如下：
 *   ```
 *   converter.adjustEncodingParams({"-b:v", "2000k", "-crf", "23"});
 *   ```
 *
 * -
 * 处理信号：可以通过连接到`qosMetrics`信号来监听流媒体转换过程中的质量指标变化，如帧率(FPS)和比特率(bitrate)。
 *   示例代码如下：
 *   ```
 *   connect(&converter, &StreamRecorder::qosMetrics,
 *           [](double fps, double bitrate){
 *               qDebug() << "Quality Metrics - FPS:" << fps << "Bitrate:" << bitrate;
 *           });
 *   ```
 */
class StreamRecorder : public QObject
{
    Q_OBJECT
public:
    enum Error {
        OUTPUT_DIR_NOT_EXIST_ERROR = 1000,
        INSUFFICIENT_DISK_SPACE_ERROR,
        CREATE_SEGMENTS_DIR_ERROR,
        INIT_RECORD_PROCESS_ERROR,
        PROCESS_NOT_RUNNING_ERROR,
        START_RECORD_PROCESS_ERROR,
        RECORD_PROCESS_TERMINATED_ERROR,
        RECORD_PROCESS_NO_RESPONSE_ERROR,
        CANT_ACCESS_STREAM_SOURCE_ERROR,
        RECORD_PROCESS_ENCODING_ERROR,
        MAXIMUM_RETRIES_ERROR,
        TERMINATE_ACTIVELY_ERROR,
        INVALID_STREAM_URL_ERROR,
        RECORD_PROCESS_CRASHED_ERROR,
        RECORD_PROCESS_ERROR,
        MERGE_FAILED_ERROR,
        NO_SEGMENTS_ERROR
    };

    explicit StreamRecorder(const StreamRecorderConfig& config, QObject* parent = nullptr);
    ~StreamRecorder();

    void setConfig(const StreamRecorderConfig& config) { m_config = config; }
    bool isRunning() const;
    bool start();
    void stop();
    void terminate();

Q_SIGNALS:
    void qosMetrics(double fps, double bitrate);
    void positionChanged(qint64 pos);
    void finished(const QString& filename, qint64 duration);
    void errorOccurred(int error, const QString& message);

private:
    void initFFmpegProcess();
    void initQoSTimers();
    void setupHardwareAcceleration();
    bool startConversion();
    void parseOutput();
    void processLine(const QByteArray& line);
    double calculateAverage(const QList<double>& values) const;
    void calculateQoSMetrics();
    void adjustBandwidth();
    void updateEncodingParams(int newBitrate);
    void handleProcessExit(int exitCode, QProcess::ExitStatus exitStatus);
    void finalizeConversion();
    void cleanup();
    void sendFFmpegCommand(const QString& cmd);

    bool checkDiskSpace();
    void handleProcessError(QProcess::ProcessError error);
    void checkProcessHealth();
    void handleError(int error, const QString& message);
    void handleMergeFinished(const QString& outputPath);
    void handleMergeError(int error, const QString& message);

    // 成员变量
    StreamRecorderConfig m_config;
    QProcess* m_process = nullptr;
    QTimer* m_watchdogTimer = nullptr;
    QTimer* m_qosTimer = nullptr;
    SegmentsMerger* m_merger = nullptr;
    QDateTime m_startTime;
    QString m_segmentsDir;
    QList<QString> m_segmentFiles;
    QList<double> m_fpsHistory;
    QList<double> m_bitrateHistory;
    int m_processedFrames = 0;
    qint64 m_lastValidPosition = 0;
    std::atomic_flag m_active = ATOMIC_FLAG_INIT;
    std::atomic<bool> m_stopRequested { false };
    std::atomic<bool> m_terminateRequested { false };
    double m_currentFps = 0;
    double m_currentBitrate = 0;
    StreamInfo m_streamInfo;
    QByteArray m_buffer;
    QDateTime m_lastOutputTime;
};

#endif // STREAMRECORDER_H
